_require local "../../basis.smi"
_require "../../smlformat-lib.smi"
_require "./Numeric.smi"
_require "./builtintypes/timestamp/TimeStamp.smi"

structure SMLSharp_SQL_Query =
struct

  type id = string
  type oper = string

  datatype 'w ascdesc_ast =
      ASC
    | DESC

  datatype 'w distinct_ast =
      ALL
    | DISTINCT

  datatype 'w db =
      DB

  datatype 'w table_id =
      TABLEID of 'w db * id

  datatype const =
      NULL
    | INT of int
    | WORD of word
    | REAL of real
    | REAL32 of real32
    | STRING of string
    | CHAR of char
    | BOOL of bool
    | INTINF of intInf
    | TIMESTAMP of SMLSharp_SQL_TimeStamp.timestamp
    | NUMERIC of SMLSharp_SQL_Numeric.num

  datatype 'w exp_ast =
      CONST of const
    | COLUMN1 of id
    | COLUMN2 of id * id
    | FUNCALL of id * 'w exp_ast list
    | OR of 'w exp_ast * 'w exp_ast
    | AND of 'w exp_ast * 'w exp_ast
    | NOT of 'w exp_ast
    | CMPOP of 'w exp_ast * oper * 'w exp_ast
    | ADDOP of 'w exp_ast * oper * 'w exp_ast
    | MULOP of 'w exp_ast * oper * 'w exp_ast
    | OP2 of 'w exp_ast * oper * 'w exp_ast
    | UNARYOP of oper * 'w exp_ast
    | IS of 'w exp_ast * oper
    | IS_NOT of 'w exp_ast * oper
    | EXP_SUBQUERY of 'w query_ast
    | EXISTS of 'w query_ast

  and 'w table_ast =
      TABLE of 'w table_id
    | TABLE_AS of 'w table_ast * id
    | TABLE_SUBQUERY of 'w query_ast
    | JOIN of 'w table_ast * 'w table_ast * 'w exp_ast
    | INNERJOIN of 'w table_ast * 'w table_ast * 'w exp_ast
    | CROSSJOIN of 'w table_ast * 'w table_ast
    | NATURALJOIN of 'w table_ast * 'w table_ast

  and 'w select_ast =
      SELECT of 'w distinct_ast option * (id * 'w exp_ast) list

  and 'w from_ast =
      FROM of 'w table_ast list

  and 'w whr_ast =
      WHERE of 'w exp_ast

  and 'w orderby_ast =
      ORDERBY of ('w exp_ast * 'w ascdesc_ast option) list

  and 'w limit_ast =
      LIMIT of {limit : 'w exp_ast option, offset : 'w exp_ast option}
    | OFFSET of {offset : 'w exp_ast * string,
                 fetch : (string * 'w exp_ast option * string) option}

  and 'w groupby_ast =
      GROUPBY of 'w exp_ast list * 'w having_ast option

  and 'w having_ast =
      HAVING of 'w exp_ast

  and 'w query_ast =
      QUERY of 'w select_ast
               * 'w from_ast
               * 'w whr_ast option
               * 'w groupby_ast option
               * 'w orderby_ast option
               * 'w limit_ast option

  datatype 'w insert_value_ast =
      VALUE of 'w exp_ast
    | DEFAULT

  datatype 'w insert_values_ast =
      INSERT_VALUES of 'w insert_value_ast list list
    | INSERT_SELECT of 'w query_ast

  datatype 'w command_ast =
      QUERY_COMMAND of 'w query_ast
    | INSERT of 'w table_id * id list option * 'w insert_values_ast
    | UPDATE of 'w table_id * (id * 'w exp_ast) list * 'w whr_ast option
    | DELETE of 'w table_id * 'w whr_ast option
    | BEGIN
    | COMMIT
    | ROLLBACK
    | CREATE_TABLE of id * (id * {ty : string, nullable : bool}) list
    | SEQ of 'w command_ast * 'w command_ast

  val format_command_ast
      : unit -> 'w command_ast -> SMLFormat.FormatExpression.expression list
  val format_query_ast
      : unit -> 'w query_ast -> SMLFormat.FormatExpression.expression list
  val format_exp_ast
      : unit -> 'w exp_ast -> SMLFormat.FormatExpression.expression list

end
